﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows.Threading;

namespace BloggerAutoPoster.Common.Mvvm
{
    //from: http://www.julmar.com/blog/mark/2009/04/01/AddingToAnObservableCollectionFromABackgroundThread.aspx
    public class MtObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
    {
        #region Delegates and Events (1)

        // Events (1) 

        public override event NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion Delegates and Events

        #region Methods (1)

        // Protected Methods (1) 

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            var eh = CollectionChanged;
            if (eh == null) return;

            var dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                              let dpo = nh.Target as DispatcherObject
                              where dpo != null
                              select dpo.Dispatcher).FirstOrDefault();

            if (dispatcher != null && dispatcher.CheckAccess() == false)
            {
                dispatcher.Invoke(DispatcherPriority.ApplicationIdle/*.DataBind*/,
                                    (System.Action)(() => OnCollectionChanged(e)));
            }
            else
            {
                foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
                    nh.Invoke(this, e);
            }
        }

        #endregion Methods

        public MtObservableCollection()
            : base()
        {
            this.CollectionChanged += TrulyObservableCollection_CollectionChanged;
        }

        void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged += EntityViewModelPropertyChanged;
                }
            }
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged -= EntityViewModelPropertyChanged;
                }
            }
        }

        void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (OnItemPropertyChanged != null) OnItemPropertyChanged(sender);
        }

        public Action<object> OnItemPropertyChanged { set; get; }
    }
}
